#ifndef __MQ_ROUTE_
#define __MQ_ROUTE_
#include "../mqcommon/mq_log.hpp"
#include "../mqcommon/mq_tools.hpp"
#include "../mqcommon/mq_msg.pb.h"

namespace MQ
{
    class Router
    {
    public:
        static bool isLegalRoutingKey(const std::string &routingkey)
        {
            for (auto e : routingkey)
            {
                if ((e >= 'a' && e <= 'z') || (e >= 'A' && e <= 'Z') || (e >= '0' && e <= '9') || e == '_' || e == '.')
                    continue;
                return false;
            }
            return true;
        }

        static bool isLegalBindingKey(const std::string &bindingkey)
        {
            // 相关字符 a~z A~Z 0~9 _ . * #
            for (auto e : bindingkey)
            {
                if ((e >= 'a' && e <= 'z') || (e >= 'A' && e <= 'Z') || (e >= '0' && e <= '9') || e == '_' || e == '.' || e == '*' || e == '#')
                    continue;
                return false;
            }
            // *和#必须独立存在
            std::vector<std::string> vec;
            SplitHelper::split(bindingkey, ".", vec);
            for (auto str : vec)
            {
                if (str.size() > 1 && str.find('*') != std::string::npos || str.find('#') != std::string::npos) // new.music.po*.不可
                    return false;
            }
            // *和#不能连续存在
            for (int i = 0; i < vec.size() - 1; ++i)
            {
                if (vec[i] == "*" && vec[i + 1] == "#")
                    return false;
                if (vec[i] == "#" && vec[i + 1] == "#")
                    return false;
                if (vec[i] == "#" && vec[i + 1] == "*")
                    return false;
            }
            return true;
        }

        static bool route(MQ::ExchangeType type, const std::string &routingkey, const std::string &bindingkey)
        {
            if (type == MQ::ExchangeType::DIRECT)
                return routingkey == bindingkey;
            else if (type == MQ::ExchangeType::BROADCAST)
                return true;
            else if (type == MQ::ExchangeType::UNKNOWNTYPE)
                return false;

            // 初始化字符串数组
            std::vector<std::string> bkey, rkey;
            size_t rk_size = SplitHelper::split(routingkey, ".", rkey);
            size_t bk_size = SplitHelper::split(bindingkey, ".", bkey);
            // 初始化二维数组
            std::vector<std::vector<bool>> dp(bk_size + 1, std::vector<bool>(rk_size + 1, false));
            dp[0][0] = true;

            if (bkey[0] == "#") // #.aaa和aaa
                dp[1][0] = true;

            // 4. 使用routing_key中的每个单词与binding_key中的每个单词进行匹配并标记数组
            for (int i = 1; i <= bk_size; ++i)
            {
                for (int j = 1; j <= rk_size; ++j)
                {
                    // 如果当前bkey是个*，或者两个单词相同，表示单词匹配成功，则从左上方继承结果
                    if (bkey[i - 1] == rkey[j - 1] || bkey[i - 1] == "*")
                        dp[i][j] = dp[i - 1][j - 1];
                    // 如果当前bkey是个#，则需要从左上，左边，上边继承结果
                    else if (bkey[i - 1] == "#")
                        dp[i][j] = dp[i - 1][j] | dp[i][j - 1] | dp[i - 1][j - 1]; // aaa.bbb和# aaa.# 和aaa
                }
            }
            return dp[bk_size][rk_size];
        }
    };
}
#endif